package controllers;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;

import dao.CategoryDAORemote;
import dao.DomainDAORemote;
import dao.QuestionDAORemote;
import dao.TemplateDAORemote;
import dto.CategoryDTO;
import dto.DomainDTO;
import dto.TemplateCategoryDTO;
import dto.TemplateDTO;

/**
 * @author andrasic
 * 
 */
@ManagedBean
@SessionScoped
public class TemplateController implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@EJB
	TemplateDAORemote templateDAO;
	@EJB
	DomainDAORemote domainDAO;
	@EJB
	CategoryDAORemote categoryDAO;
	@EJB
	QuestionDAORemote questionDAO;

	@ManagedProperty(value = "#{templateDTO}")
	TemplateDTO templateDTO;

	private List<DomainDTO> domains;
	private List<CategoryDTO> categories;
	private String selectedDomain;
	private String selectedCategory;
	private int selectedCategoryID;
	private String selectedQuestionNumber;
	private int questionsPerCategory = 0;
	private boolean visible = false;
	private boolean domainList = false;
	private boolean categoryList = false;
	private boolean addButton = false;
	private String errorMessage;
	private String successMessage;
	private String deleteButton;

	/**
	 * Initializes fields.
	 */
	@PostConstruct
	public void initDomains() {
		domains = new ArrayList<DomainDTO>();
		domains.clear();
		domains = domainDAO.findAllDomains();
		selectedDomain = domains.get(0).getName();
		categories = new ArrayList<CategoryDTO>();
		categories.clear();
		categories = categoryDAO.getCategoryByDomain(domainDAO
				.getIdByDomainName(selectedDomain));
		selectedCategory = categories.get(0).getName();
		selectedCategoryID = categories.get(0).getId();
		questionsPerCategory = questionDAO.getAllValidQuestionsByCategory(
				categoryDAO.getCategoryById(selectedCategoryID)).size();
		errorMessage = "";
		successMessage = "";
		templateDTO.setTitle("");
		templateDTO.setDuration(0);
		if (templateDTO.getTemplateCategories() != null)
			templateDTO.getTemplateCategories().clear();
		selectedQuestionNumber = "";
		visible = false;
		domainList = false;
		categoryList = false;
		addButton = false;
	}

	/**
	 * Adds a newly created template to the database. The template must have a
	 * title, a duration greater than 0 and must have at least one category
	 * added from which questions are to be generated.
	 * 
	 * @return a message of error or success
	 * @throws Exception
	 *             if template could not be added to the database or if the
	 *             categories could not be set for the template.
	 */
	public String add() throws Exception {
		boolean flag = true;
		if (templateDTO.getTitle().equals("")) {
			errorMessage = "Title field must not be empty!";
			flag = false;
			return "error";
		} else if (templateDTO.getDuration() == 0) {
			errorMessage = "Test time must be greater than 0!";
			flag = false;
			return "error";
		} else if (templateDTO.getTemplateCategories() == null
				|| templateDTO.getTemplateCategories().size() == 0) {
			flag = false;
			errorMessage = "At least one category must be chosen!";
			return "error";
		} else {
			List<TemplateCategoryDTO> tcDTO = new ArrayList<TemplateCategoryDTO>();
			int id = templateDAO.addTemplate(templateDTO);
			for (TemplateCategoryDTO tc : templateDTO.getTemplateCategories()) {
				tcDTO.add(tc);
			}
			if (id != 0)
				templateDAO.addTempCatToTemplate(id, tcDTO);
			tcDTO.clear();
			templateDTO.setTitle("");
			templateDTO.setDuration(0);
			templateDTO.getTemplateCategories().clear();
			selectedQuestionNumber = "";
			visible = false;
			domainList = false;
			categoryList = false;
			addButton = false;
			flag = true;
			selectedDomain = domains.get(0).getName();
			categories.clear();
			categories = categoryDAO.getCategoryByDomain(domainDAO
					.getIdByDomainName(selectedDomain));
		}
		if (flag == true) {
			successMessage = "Template successfully created!";
		}
		return "ok";
	}

	/**
	 * Deletes category from a template and adds it back to the list of
	 * categories.
	 * 
	 * @param id
	 *            category id of category to be deleted from those belonging to
	 *            the current template.
	 */
	public void delete(String id) {
		int index = 0;
		if (templateDTO.getTemplateCategories() != null) {
			for (TemplateCategoryDTO tc : templateDTO.getTemplateCategories())
				if (tc.getCategory().getId() == Integer.parseInt(id)) {
					index = templateDTO.getTemplateCategories().indexOf(tc);
				}
			categories.add(templateDTO.getTemplateCategories().get(index)
					.getCategory());
			templateDTO.getTemplateCategories().remove(index);
		}
		if (templateDTO.getTemplateCategories().size() == 0) {
			domainList = false;
			visible = false;

		}
		categoryList = false;
		addButton = false;
	}

	/**
	 * Populates list of categories for the currently selected domain.
	 * 
	 * @param e
	 *            triggered AjaxBehaviorEvent.
	 */
	public void populateCategories(AjaxBehaviorEvent e) {
		categoryList = false;
		successMessage = "";
		errorMessage = "";
		selectedCategory = "";
		categories.clear();
		categories = categoryDAO.getCategoryByDomain(domainDAO
				.getIdByDomainName(selectedDomain));
		if (templateDTO.getTemplateCategories() != null) {
			List<CategoryDTO> removeIndex = new ArrayList<CategoryDTO>();
			for (TemplateCategoryDTO tc : templateDTO.getTemplateCategories()) {
				for (CategoryDTO cDTO : categories)
					if (cDTO.getId() == tc.getCategory().getId()) {
						removeIndex.add(cDTO);
					}
			}
			for (CategoryDTO cDTO : removeIndex) {
				categories.remove(cDTO);
			}
		}
		if (categories.size() > 0) {
			selectedCategory = categories.get(0).getName();
			selectedCategoryID = categories.get(0).getId();
			questionsPerCategory = questionDAO.getAllValidQuestionsByCategory(
					categoryDAO.getCategoryById(selectedCategoryID)).size();
		} else {
			questionsPerCategory = 0;
		}

	}

	/**
	 * Updates the number of available category questions that exist for the
	 * current selected category.
	 * 
	 * @param e
	 *            triggered AjaxBehaviorEvent.
	 * @throws Exception
	 *             if the getCategoryByNameDomain method fails to execute
	 *             successfully.
	 */
	public void updateQuestionsPerCateg(AjaxBehaviorEvent e) throws Exception {
		successMessage = "";
		errorMessage = "";
		if (!selectedCategory.equals("")) {
			selectedCategoryID = categoryDAO.getCategoryByNameDomain(
					selectedCategory,
					domainDAO.getIdByDomainName(selectedDomain)).getId();
			questionsPerCategory = questionDAO.getAllValidQuestionsByCategory(
					categoryDAO.getCategoryById(selectedCategoryID)).size();
		} else {
			questionsPerCategory = 0;
		}
	}

	/**
	 * Adds selected categories to current new template.
	 */
	public void addSelectedCategories() {
		successMessage = "";
		errorMessage = "";
		TemplateCategoryDTO tcDTO = new TemplateCategoryDTO();
		if (templateDTO.getTemplateCategories() == null)
			templateDTO
					.setTemplateCategories(new ArrayList<TemplateCategoryDTO>());
		if (selectedDomain != null && !selectedDomain.equals("")
				&& selectedCategory != null && !selectedCategory.equals("")) {
			if (selectedQuestionNumber != null
					&& !selectedQuestionNumber.equals("")) {
				try {
					Integer.parseInt(selectedQuestionNumber);
					if (Integer.parseInt(selectedQuestionNumber) > 0) {
						if (Integer.parseInt(selectedQuestionNumber) <= questionsPerCategory) {
							for (CategoryDTO c : categoryDAO
									.getCategoryByDomain(domainDAO
											.getIdByDomainName(selectedDomain))) {
								if (c.getName().equalsIgnoreCase(
										selectedCategory)) {

									tcDTO.setCategory(c);
									tcDTO.setTemplate(templateDTO);
									tcDTO.setNumberOfQuestions(Integer
											.parseInt(selectedQuestionNumber));
									templateDTO.getTemplateCategories().add(
											tcDTO);
									deleteButton = c.getId() + "";
								}
							}
							List<CategoryDTO> removeIndex = new ArrayList<CategoryDTO>();
							for (TemplateCategoryDTO tc : templateDTO
									.getTemplateCategories()) {
								for (CategoryDTO cDTO : categories)
									if (cDTO.getId() == tc.getCategory()
											.getId()) {
										removeIndex.add(cDTO);
									}
							}
							for (CategoryDTO cDTO : removeIndex) {
								categories.remove(cDTO);
							}
							if (categories.size() > 0) {
								selectedCategory = categories.get(0).getName();
								selectedCategoryID = categories.get(0).getId();
								questionsPerCategory = questionDAO
										.getAllValidQuestionsByCategory(
												categoryDAO
														.getCategoryById(categories
																.get(0).getId()))
										.size();
							} else {
								categoryList = true;
								addButton = true;
							}
							domainList = true;
							if (visible == false) {
								visible = true;
								try {
									FacesContext
											.getCurrentInstance()
											.getExternalContext()
											.redirect(
													"/MSGCandidateTesting/faces/createTemplate.xhtml");
								} catch (IOException ex) {
									ex.printStackTrace();
								}
							}
						} else {
							errorMessage = "Not enough questions available!";
						}
					} else {
						errorMessage = "Number of questions must be greater than 0!";
					}
				} catch (NumberFormatException ex) {
					errorMessage = "Input must be a number!";
				}
			} else {
				errorMessage = "Number of questions must be greater than 0!";
			}
		}
	}

	public int getQuestionsPerCategory() {
		return questionsPerCategory;
	}

	public void setQuestionsPerCategory(int questionsPerCategory) {
		this.questionsPerCategory = questionsPerCategory;
	}

	public boolean getVisible() {
		return visible;
	}

	public void setVisible(boolean visible) {
		this.visible = visible;
	}

	public boolean isDomainList() {
		return domainList;
	}

	public void setDomainList(boolean domainList) {
		this.domainList = domainList;
	}

	public boolean isCategoryList() {
		return categoryList;
	}

	public void setCategoryList(boolean categoryList) {
		this.categoryList = categoryList;
	}

	/**
	 * @return the addButton
	 */
	public boolean isAddButton() {
		return addButton;
	}

	/**
	 * @param addButton
	 *            the addButton to set
	 */
	public void setAddButton(boolean addButton) {
		this.addButton = addButton;
	}

	public String getSelectedCategory() {
		return selectedCategory;
	}

	public void setSelectedCategory(String selectedCategory) {
		this.selectedCategory = selectedCategory;
	}

	public String getSelectedQuestionNumber() {
		return selectedQuestionNumber;
	}

	public void setSelectedQuestionNumber(String selectedQuestionNumber) {
		this.selectedQuestionNumber = selectedQuestionNumber;
	}

	public TemplateDTO getTemplateDTO() {
		return templateDTO;
	}

	public void setTemplateDTO(TemplateDTO templateDTO) {
		this.templateDTO = templateDTO;
	}

	public List<DomainDTO> getDomains() {
		domains.clear();
		domains = domainDAO.findAllDomains();
		return domains;
	}

	public void setDomains(List<DomainDTO> domains) {
		this.domains = domains;
	}

	public List<CategoryDTO> getCategories() {
		return categories;
	}

	public void setCategories(List<CategoryDTO> categories) {
		this.categories = categories;
	}

	public void setSelectedDomain(String selectedDomain) {
		this.selectedDomain = selectedDomain;
	}

	public String getSelectedDomain() {
		return selectedDomain;
	}

	public int getSelectedCategoryID() {
		return selectedCategoryID;
	}

	public void setSelectedCategoryID(int selectedCategoryID) {
		this.selectedCategoryID = selectedCategoryID;
	}

	public String getErrorMessage() {
		return errorMessage;
	}

	public void setErrorMessage(String errorMessage) {
		this.errorMessage = errorMessage;
	}

	public String getSuccessMessage() {
		return successMessage;
	}

	public void setSuccessMessage(String successMessage) {
		this.successMessage = successMessage;
	}

	public void setDeleteButton(String deleteButton) {
		this.deleteButton = deleteButton;
	}

	public String getDeleteButton() {
		return deleteButton;
	}

}
